package com.hxw.sample.opengl30;

import android.opengl.GLES30;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;

import com.hxw.sample.opengl30.uitls.ShaderUtil;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

/**
 * 在三角形渲染的基础上，利用矩阵，实现旋转，位移，镜像等功能
 */
public class TriangleRenderV2_MAT implements GLSurfaceView.Renderer{

    //顶点绘制脚本
    private static final String vertex_shader =
            "uniform mat4 mTMatrix;"+//变换矩阵
            "attribute vec4 vPosition;\n" +//顶点坐标，我们需要在Java获取到这个值并赋值
            "void main() {\n" +
            "  gl_Position = mTMatrix*vPosition;\n" +//gl_Position是OpenGL内部变量，OpenGL通过该值获取顶点位置
            "}";

    //纹理绘制脚本（在顶点的基础上，加上颜色或图像就是纹理）
    private static final String fragment_shader = "precision mediump float;//浮点数精度\n" +
            "uniform vec4 vColor;\n" +//纹理颜色,uniform的意思是全局变量，仅当为uniform类型时，才能在Java获取片元中变量并赋值
            "void main() {\n" +
            "    gl_FragColor = vColor;\n" +//gl_FragColor是OpenGL内部变量，OpenGL通过该值获取像素点的纹理
            "}";

    //一个顶点通常用x,y,z这三个值来表示，但如果是二维，则z可有可无，为0即可
    private final float[] VERTEX ={
            -1f, 0f ,0f,//v1
            0f, -1f ,0f,//v2
            0f, 1f ,0f, //v3
    };
    private FloatBuffer mVertexBuffer;

    private final float[] COLOR = {0.5f,0.5f,0.5f,1.0f};//纹理颜色通常用4个值对应，分别为：R,G,B,A

    private final float[] mTranslateMatrix = new float[16];//定义一个4x4的变换矩阵

    private int mProgram,mPositionHandle,mColorHandle,mTMatrixHandle;

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        mVertexBuffer = ByteBuffer.allocateDirect(VERTEX.length*4)//float占4个字节，所以乘以4
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer()
                .put(VERTEX);
        mVertexBuffer.position(0);

        Matrix.setIdentityM(mTranslateMatrix,0);//设置为单位矩阵

//        Matrix.translateM(mTranslateMatrix,0,0.5f,0,0);
        //平移：参数2为偏移量，通常为0，参数3为x，4为y，5为z
        //注：这里为归一化处理,屏幕中间为0，最左边为-1，最右边为1，顶部为1，底部为-1,因此第三个参数0.5相当于向右移动View的1/4宽

//        Matrix.scaleM(mTranslateMatrix,0,0.5f,0.5f,1.0f);//缩放：宽高都缩小一半

        Matrix.scaleM(mTranslateMatrix, 0, -1f, 1f, 1f);//镜像：左右镜像

//        Matrix.rotateM(mTranslateMatrix,0,90f,0f,0f,1F);//旋转:旋转90度

        //程序必须在onSurfaceCreated之后加载才行，否则OpenGL环境未就绪是无法正常加载的
        mProgram = ShaderUtil.createProgram(vertex_shader,fragment_shader);

        if (mProgram != 0){
            mPositionHandle = GLES30.glGetAttribLocation(mProgram,"vPosition");//获取顶点脚本中的vPosition变量的句柄
            mColorHandle = GLES30.glGetUniformLocation(mProgram,"vColor");//获取纹理脚本中的vColor变量的句柄
            mTMatrixHandle = GLES30.glGetUniformLocation(mProgram,"mTMatrix");
        }

        GLES30.glClearColor(1,0,0,1f);//设置清空View时的背景色
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        GLES30.glViewport(0,0,width,height);//绘制的区间
    }

    @Override
    public void onDrawFrame(GL10 gl) {

        GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);//清除颜色缓冲区

        GLES30.glUseProgram(mProgram);//指定当前渲染操作所要使用的着色器程序

        GLES30.glEnableVertexAttribArray(mPositionHandle);//设置顶点参数为可用

        GLES30.glVertexAttribPointer(mPositionHandle, 3, GLES30.GL_FLOAT, false, 12, mVertexBuffer);
        //对vPosition进行赋值
        //第二个参数为mVertexBuffer中用多少个浮点数代表顶点，如果只有x和y，那就是2，如果是xyz,那就是3
        //第五个参数为两个顶点之间的相差多少个字节，由于我们用3个浮点数代表一个顶点，一个浮点数4个字节，因此这里是12

        GLES30.glUniform4fv(mColorHandle, 1,COLOR,0);//设置纹理颜色为红色
        GLES30.glUniformMatrix4fv(mTMatrixHandle,1,false,mTranslateMatrix,0);//设置变换矩阵

        GLES30.glDrawArrays(GLES30.GL_TRIANGLE_STRIP,0, 3);//渲染，第三个参数为顶点数量

        GLES30.glDisableVertexAttribArray(mPositionHandle);//释放句柄
    }

    public void onDestroy(){
        GLES30.glDeleteProgram(mProgram);
    }
}
